package com.hmdp.service.impl;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.hmdp.dto.Result;
import com.hmdp.entity.Shop;
import com.hmdp.mapper.ShopMapper;
import com.hmdp.myconst.KeyConst;
import com.hmdp.service.IShopService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

import static com.hmdp.myconst.KeyConst.QUERY_SHOP_KEY;
import static com.hmdp.myconst.KeyConst.QUERY_SHOP_TIME;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
    @Autowired
    private ShopMapper shopMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    /**
     * 根据id查询商户
     * @param id
     * @return
     */
    @Override
    public Result queryShopById(Long id) {
        //先拼接key
       String shopKey= QUERY_SHOP_KEY+id.toString();
        //1.先去redis查询,是否存在(缓存穿透)
        Boolean hasKey = redisTemplate.hasKey(shopKey);
        String shopStr = redisTemplate.opsForValue().get(shopKey);
        //1.1存在
        if(hasKey){
            //存在,但是为空,缓存穿透
            if("null".equals(shopStr)){
                return Result.fail("此商户不存在");
            }
            //存在但是不为空,返回
            Shop shop = JSONUtil.toBean(shopStr, Shop.class);
            return Result.ok(shop);
        }
        Shop shop=null;
        //2.判断有没有加锁-缓存穿透
        try {
            //2.1有的话那么沉睡
            if(isLock()){
                Thread.sleep(50);
                queryShopById(id);
            }
            //2.2没有执行后面操作
            //2.去mysql取查询
           shop = shopMapper.selectById(id);
            //3.如果是空记录到redis
            if(ObjectUtil.isNull(shop)){
                redisTemplate.opsForValue().set(shopKey,"null");
                return Result.fail("商户为空");
            }
            //4.写入redis中
            shopStr= JSONUtil.toJsonStr(shop);
            redisTemplate.opsForValue().set(shopKey,shopStr,QUERY_SHOP_TIME, TimeUnit.MINUTES);
        }catch (Exception e){
            System.out.println(e);
        }finally {
            unlock();
        }
       //5.返回
        return Result.ok(shop);
    }

    /**
     * 更新对应的商户
     * @param shop
     */
    @Override
    public Result updateShop(Shop shop) {
        if(shop.getId() == null){
            return Result.fail("商户的id不能为空");
        }
        //1.先对redis中商户信息进行删除
        redisTemplate.delete(QUERY_SHOP_KEY+shop.getId());
        //2.然后进行修改->mysql
        shopMapper.updateById(shop);
        return Result.ok();
    }
    //缓存穿透的锁
    public static final String LOCK_KEY="cache_key";
    //判断有没有锁
    public  Boolean isLock() {
        return BooleanUtil.isTrue(redisTemplate.hasKey(LOCK_KEY));
    }
    //解锁
    public void unlock() {
        redisTemplate.delete(LOCK_KEY);
    }
}
